<template>
    <div class="map-container">
        <!-- 地图容器 -->
        <div id="map" class="map" ref="mapContainer">
            <!-- 显示经纬度 -->
            <div id="mouse-position" class="mouse-position"></div>
            <!-- 属性弹窗 -->
            <div id="popup" class="ol-popup">
                <a href="#" id="popup-closer" class="ol-popup-closer"></a>
                <div id="popup-content"></div>
            </div>
        </div>

        <BaseMapControls v-if="map" :map="map" />
        <!-- 地图工具箱 -->
        <div class="map-tools-container">
            <div v-for="(group, index) in toolGroups" :key="index" class="tool-group">
                <div class="tool-group-header" @click="toggleGroup(group)">
                    {{ group.icon }} {{ group.title }}
                    <span class="arrow">{{ group.expanded ? '▼' : '▶' }}</span>
                </div>

                <transition name="slide">
                    <div v-show="group.expanded" class="tool-group-buttons">
                        <button v-for="btn in group.buttons" :key="btn.text" @click="btn.handler">
                            {{ btn.icon }} {{ btn.text }}
                        </button>
                    </div>
                </transition>
            </div>

        </div>

        <!-- layer-control-panel -->
        <LayerControl v-if="layerControlVisible" :map="map" :layer-groups="layerGroups" />

    </div>
</template>

<script>
import LayerControl from '@/components/LayerControl.vue';
import BaseMapControls from '@/components/BaseMapControls.vue';
// import { bbox as bboxStrategy } from 'ol/loadingstrategy';
import { defaults as defaultInteractions } from 'ol/interaction';
import { Map, View } from 'ol';
import VectorTileLayer from 'ol/layer/VectorTile';
import VectorTileSource from 'ol/source/VectorTile';
import MVT from 'ol/format/MVT';
import Tile from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import { get as getProjection } from 'ol/proj';
import Overlay from 'ol/Overlay.js';
import { toStringHDMS } from 'ol/coordinate.js';
import { toLonLat } from 'ol/proj.js';
import Style from 'ol/style/Style';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
import Draw from 'ol/interaction/Draw';
import VectorSource from 'ol/source/Vector';
import VectorLayer from 'ol/layer/Vector';
import { fromLonLat } from 'ol/proj';
import tinycolor from 'tinycolor2';
import Circle from 'ol/style/Circle';


export default {
    name: 'TainDiTuMap', // 使用多词命名
    components: {
        BaseMapControls,
        LayerControl,
    },
    mounted() {
        this.initMap();
        this.mapRect = this.$refs.mapContainer.getBoundingClientRect();
        document.addEventListener('fullscreenchange', () => {
            this.fullScreen = !!document.fullscreenElement;
            this.map.updateSize();
        });
    },
    data() {
        return {
            toolGroups: [
                {
                    title: '🌐 视图控制',
                    expanded: true,
                    buttons: [
                        { text: '全图', icon: '🗺️', handler: this.zoomToFullExtent },
                        { text: '全屏', icon: '🖥️', handler: this.toggleFullScreen },
                    ]
                },
                {
                    title: '📏 测量工具',
                    expanded: false,
                    buttons: [
                        { text: '距离', icon: '📐', handler: () => this.startMeasure('LineString') },
                        { text: '面积', icon: '📊', handler: () => this.startMeasure('Polygon') }
                    ]
                },
                {
                    title: '🧰 图层与数据',
                    expanded: false,
                    buttons: [
                        { text: '图层', icon: '🎨', handler: this.toggleLayerControl },
                    ]
                },
                {
                    title: '📄 交互功能',
                    expanded: false,
                    buttons: [
                        { text: `弹窗 ${this.showPopup ? '(开)' : '(关)'}`, icon: '📄', handler: this.togglePopup },
                        { text: '复制坐标', icon: '📋', handler: this.copyCurrentCoordinate },
                        { text: '导出地图', icon: '📷', handler: this.exportMapAsImage }
                    ]
                }
            ],
            map: null,
            popupContent: '',
            popupX: 0,
            popupY: 0,
            yiyuan: null,
            mapRect: null, // 用于保存地图容器的位置信息
            layerControlVisible: false,
            layerLabels: { // 图层名称映射为中文名（可选）
                vectorLayer_building: '建筑',
                tilelayers3: '卫星影像',
                rasterTile: '栅格图层'
            },
            layerGroups: [
                {
                    name: 'base',
                    label: '基础图层',
                    layers: [
                        {
                            key: 'tilelayers3',
                            name: '卫星影像',
                            visible: true,
                            opacity: 1,
                            zIndex: 0
                        }
                    ]
                },
                {
                    name: 'vector',
                    label: '矢量图层',
                    layers: [
                        {
                            key: 'vectorLayer_building',
                            name: '建筑',
                            visible: true,
                            opacity: 1,
                            zIndex: 1
                        }
                    ]
                },
                {
                    name: 'raster',
                    label: '栅格图层',
                    layers: [
                        {
                            key: 'rasterTile',
                            name: '栅格图层',
                            visible: true,
                            opacity: 1,
                            zIndex: 1
                        }
                    ]
                }
            ],
            layerTypes: {
                vectorLayer_building: 'vector',
                tilelayers3: 'base'
            },
            measureInteraction: null,
            lastCoordinate: null,
            vectorLayer_building: null,
            tilelayers3: null,
            rasterTile: null,
            measureType: null, // 'LineString' | 'Polygon'
            measureTooltipElement: null,
            measureTooltipOverlay: null,
            showPopup: false, // 控制弹窗是否显示，默认为不显示
            vectorTileParams: { //  矢量切片参数
                name: 'roads',
                lowLevel: 0,
                highLevel: 6,
                path: 'D:\\BaiduSyncdisk\\工作\\uni-app\\f0716\\f0716\\static\\data\\shp\\acc.shp',
                savePath: 'D:\\data'
            },
            showParamsForm: false, // 显示参数表单，默认为不显示
            showRasterForm: false,
            rasterParams: {
                name: 'tif',
                lowLevel: 0,
                highLevel: 6,
                path: 'D:\\BaiduSyncdisk\\工作\\uni-app\\f0716\\f0716\\static\\data\\50.tif',
                savePath: 'D:\\data\\raster'
            },
            fullScreen: false, // 控制是否全屏
            isShpUploadExpanded: false, // 是否展开上传shp文件
            uploadedFileName: '',
            uploadError: '',
            rasterUploadExpanded: false,
            uploadedRasterName: '',
            uploadRasterError: '',
        };
    },
    methods: {
        initMap() {
            // 获取传入的地图范围参数
            const route = this.$route;
            console.log('route:', route.query.lng);
            let center = fromLonLat([120, 31]); // 默认镇江坐标
            let zoom = 15;

            if (route.query.lng && route.query.lat) {
                try {
                    const lng = parseFloat(route.query.lng);
                    const lat = parseFloat(route.query.lat);
                    center = fromLonLat([lng, lat]);
                    zoom = 16; // 放大级别
                } catch (e) {
                    console.warn('无效的地图坐标:', route.query);
                }
            }

            const view = new View({
                center: center,
                zoom: zoom,
                projection: 'EPSG:3857'
            });
            /**
              * Elements that make up the popup.
              */
            const container = document.getElementById('popup');
            const content = document.getElementById('popup-content');
            const closer = document.getElementById('popup-closer');
            /**
              * Create an overlay to anchor the popup to the map.
              */
            const overlay = new Overlay({
                element: container,
                autoPan: {
                    animation: {
                        duration: 250,
                    },
                },
            });

            /**
             * Add a click handler to hide the popup.
             * @return {boolean} Don't follow the href.
             */
            closer.onclick = function () {
                overlay.setPosition(undefined);
                closer.blur();
                return false;
            };
            this.map = new Map({ // 不赋值给 map 变量
                target: 'map',
                layers: [],
                overlays: [overlay],
                view: view,
                // 👇 禁用默认控件
                controls: [],
                interactions: defaultInteractions({
                    pinchRotate: false, // 关闭旋转
                    altShiftDragRotate: false,
                    zoomWheelFactor: 0.5, // 滚轮缩放速度
                }),
                // updateWhileInteracting: false,
                renderMode: 'fast',
            });
            // ----------------------------------
            // 地图左下角显示坐标
            const mousePositionElement = document.getElementById('mouse-position');

            this.map.getViewport().addEventListener('mousemove', (e) => {
                const pixel = this.map.getEventPixel(e);
                const coordinate = this.map.getCoordinateFromPixel(pixel);

                // 将 EPSG:3857 坐标转换为 WGS84（经纬度）
                const [lon, lat] = toLonLat(coordinate);

                // 显示并保留 6 位小数
                mousePositionElement.textContent = `经度: ${lon.toFixed(6)}, 纬度: ${lat.toFixed(6)}`;
            });
            // ----------------------------------
            // 地图点击事件
            this.map.on('singleclick', (evt) => {
                if (!this.showPopup) {
                    return; // 如果关闭了，则不执行弹窗逻辑
                }
                const pixel = evt.pixel;
                const coordinate = evt.coordinate;
                // 保存点击坐标，用于测量距离和面积
                this.lastCoordinate = coordinate;
                // 获取点击位置的 feature
                const feature = this.map.forEachFeatureAtPixel(pixel, (feature) => {
                    return feature;
                });

                if (feature) {
                    // 获取 feature 的属性
                    const properties = feature.getProperties();
                    // 获取 feature 所属图层名称
                    const layer = this.map.getLayers().item(1);
                    console.log(layer);
                    const layerName = layer && layer.get('name') ? layer.get('name') : '未知图层';

                    // 构建表格 HTML
                    let tableHtml = `
                        <p>图层：<strong>${layerName}</strong></p>
                        <table style="width:100%; border-collapse: collapse; margin-top: 8px;">
                            <thead>
                            <tr style="background-color: #f2f2f2;">
                                <th style="text-align:center; padding: 6px; border: 1px solid #ccc;">属性名</th>
                                <th style="text-align:center; padding: 6px; border: 1px solid #ccc;">属性值</th>
                            </tr>
                            </thead>
                            <tbody>
                        `;

                    Object.entries(properties).forEach(([key, value]) => {
                        tableHtml += `
                            <tr>
                            <td style="padding: 4px 6px; border: 1px solid #ccc;">${key}</td>
                            <td style="padding: 4px 6px; border: 1px solid #ccc;">${value}</td>
                            </tr>
                        `;
                    });

                    tableHtml += '</tbody></table>';

                    content.innerHTML = tableHtml;
                } else {
                    // 没有点中要素时显示坐标
                    const hdms = toStringHDMS(toLonLat(coordinate));
                    content.innerHTML = '<p>你点击的位置：</p><code>' + hdms + '</code>';
                }

                overlay.setPosition(coordinate);
            });
            this.addLayer();
            this.initLayerControl();
        },
        addLayer() {
            // ----------------------------------
            // 添加矢量瓦片图层
            var layerName = 'roads'; // 动态变量
            this.vectorLayer_building = new VectorTileLayer({
                title: "vector",
                name: "OSM道路",
                source: new VectorTileSource({
                    format: new MVT(),
                    url: `http://124.70.132.64:8031/spatial/vectorPostGisTile/{z}/{x}/{y}.pbf?name=${layerName}`,
                    projection: getProjection('EPSG:3857'),
                    minZoom: 10,
                }),
                // 使用 ol.style.Style 设置样式
                // style: new Style({
                //   fill: new Fill({
                //     color: '#FF0000' // 统一填充红色
                //   }),
                //   stroke: new Stroke({
                //     color: '#000000', // 黑色边框
                //     width: 1
                //   })
                // })
            });
            var layerName1 = 'yiyuan3857'; // 动态变量
            this.yiyuan = new VectorTileLayer({
                title: "vector",
                name: "医院",
                source: new VectorTileSource({
                    format: new MVT(),
                    url: `http://124.70.132.64:8031/spatial/vectorPostGisTile/{z}/{x}/{y}.pbf?name=${layerName1}`,
                    projection: getProjection('EPSG:3857'),
                }),
                style: new Style({
                    image: new Circle({
                        radius: 6,
                        fill: new Fill({
                            color: '#e74c3c' // 红色填充
                        }),
                        stroke: new Stroke({
                            color: '#ffffff', // 白色描边
                            width: 2
                        })
                    })
                })
            });

            // layerName = 'roads';
            // const vectorLayer_roads = new VectorTileLayer({
            //   title: layerName,
            //   source: new VectorTileSource({
            //     format: new MVT(),
            //     url: `http://localhost:8031/spatial/vectorPostGisTile/{z}/{x}/{y}.pbf?name=${layerName}`,
            //     projection: getProjection('EPSG:3857'),
            //   }),
            // });
            this.tilelayers3 = new Tile({
                title: "base",
                name: "天地图影像图层",
                source: new XYZ({
                    url: 'http://t0.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=053318a29e7ee8be40a0958754cc1827',//053318a29e7ee8be40a0958754cc1827  ；   44ee7488efb523f6c21e2cd4448c79eb
                    attributions: "天地图卫星影像",
                    crossOrigin: "anonymous",
                    wrapX: false,
                    maxZoom: 17
                })
            })

            this.map.addLayer(this.tilelayers3);
            this.map.addLayer(this.vectorLayer_building);
            this.map.addLayer(this.yiyuan);
            this.animateFlowLine();
        },
        createRasterLayer(urlTemplate, layerName = '栅格图层') {
            return new Tile({
                title: "raster",
                name: layerName,
                source: new XYZ({
                    url: urlTemplate,
                    attributions: "栅格图层数据 © 自定义服务",
                    crossOrigin: "anonymous",
                    wrapX: false,
                }),
            });
        },
        animateFlowLine() {
            const CLASS_COLOR_MAP = {
                'primary': '#FF0000',     // 主干道：红色
                'secondary': '#FFA500',   // 次干道：橙色
                'tertiary': '#FFD700',    // 三级道路：金色
                'residential': '#8B4513', // 居住区道路：棕色
                'unclassified': '#A9A9A9' // 未分类道路：灰色
            };

            const getDynamicStyle = (zoom) => {
                return function (feature) {
                    const fclass = feature.get('fclass') || 'unclassified';
                    let baseColor = CLASS_COLOR_MAP[fclass] || CLASS_COLOR_MAP['unclassified'];
                    // 缩小时仅显示主干道
                    if (zoom < 10 && !['primary', 'secondary'].includes(fclass)) {
                        return null; // 不绘制非主要道路
                    }
                    // 根据缩放级别调整颜色深浅（缩放越小表示路网越密集）
                    let darkenFactor = 0;
                    if (zoom < 10) {
                        darkenFactor = 0.3; // 路网密集，颜色更亮
                    } else if (zoom < 12) {
                        darkenFactor = 0.15;
                    }

                    let color = darkenColor(baseColor, darkenFactor);

                    // 根据缩放级别调整线宽
                    let strokeWidth = 2;
                    if (zoom < 10) {
                        strokeWidth = 3; // 密集区域加粗显示
                    } else if (zoom < 12) {
                        strokeWidth = 2.5;
                    }

                    // 创建样式对象
                    return new Style({
                        stroke: new Stroke({
                            color: color,
                            width: strokeWidth
                        })
                    });
                };
            };

            // 将颜色变暗的函数
            function darkenColor(color, factor) {
                const hsl = tinycolor(color).toHsl();
                hsl.l = Math.max(0.2, hsl.l - factor); // 降低亮度
                return tinycolor(hsl).toRgbString();   // 返回 RGB 字符串
            }

            // 初始化样式
            let currentZoom = Math.round(this.map.getView().getZoom());
            this.vectorLayer_building.setStyle(getDynamicStyle(currentZoom));

            // 监听缩放变化并更新样式
            this.map.getView().on('change:resolution', () => {
                const zoom = Math.round(this.map.getView().getZoom());
                if (zoom !== currentZoom) {
                    currentZoom = zoom;
                    this.vectorLayer_building.setStyle(getDynamicStyle(zoom));
                }
            });
        },
        zoomToFullExtent() {
            const view = this.map.getView();

            // 镇江市 WGS84 范围
            const bounds = {
                west: 120.5,
                south: 30.8,
                east: 121.5,
                north: 31.6
            };

            // 转换为 EPSG:3857 坐标
            const jiangsuExtent = [
                ...fromLonLat([bounds.west, bounds.south]),
                ...fromLonLat([bounds.east, bounds.north])
            ];
            view.fit(jiangsuExtent, {
                duration: 1000,
                padding: [50, 50, 50, 50]
            });
        },
        exportMapAsImage() {
            const mapCanvas = this.map.getViewport().querySelector('canvas');
            const dataURL = mapCanvas.toDataURL('image/png');

            const link = document.createElement('a');
            link.href = dataURL;
            link.download = 'map-screenshot.png';
            link.click();
        },
        toggleLayerControl() {
            this.layerControlVisible = !this.layerControlVisible;
            console.log('Layer control visibility:', this.layerControlVisible);
        },

        syncLayerList() {
            const currentNames = this.map.getLayers().getArray()
                .map(l => l.get('name'));

            this.layerGroups = this.layerGroups.map(group => ({
                ...group,
                layers: group.layers.filter(l => currentNames.includes(l.key))
            }));
        },
        setLayerOpacity(layer) {
            const olLayer = this.map.getLayers().getArray().find(l => l.get('name') === layer.key);
            if (olLayer) {
                olLayer.setOpacity(layer.opacity);
            }
        },
        copyCurrentCoordinate() {
            if (this.lastCoordinate) {
                const coordStr = this.lastCoordinate.join(', ');
                navigator.clipboard.writeText(coordStr).then(() => {
                    alert('坐标已复制到剪贴板：' + coordStr);
                }).catch(err => {
                    alert('复制失败：' + err);
                });
            } else {
                alert('请先点击地图获取坐标');
            }
        },
        startMeasure(type) {
            const map = this.map;
            const source = new VectorSource();

            const vectorLayer = new VectorLayer({
                title: 'Measurement Layer',
                source: source,
                style: new Style({
                    stroke: new Stroke({
                        color: '#ff0000',
                        width: 2
                    }),
                    fill: new Fill({
                        color: 'rgba(255, 0, 0, 0.2)'
                    })
                })
            });

            map.addLayer(vectorLayer);

            // 创建测量提示元素
            if (this.measureTooltipOverlay) {
                map.removeOverlay(this.measureTooltipOverlay);
            }

            const tooltipElement = document.createElement('div');
            tooltipElement.className = 'ol-tooltip';
            this.measureTooltipElement = tooltipElement;

            const tooltipOverlay = new Overlay({
                element: tooltipElement,
                offset: [15, -15],
                positioning: 'bottom-center'
            });
            this.measureTooltipOverlay = tooltipOverlay;
            map.addOverlay(tooltipOverlay);

            // 创建 Draw 交互
            const drawInteraction = new Draw({
                source: source,
                type: type,
                freehand: false
            });

            this.measureInteraction = drawInteraction;

            // 显示实时长度/面积
            let sketch;
            let listener;

            drawInteraction.on('drawstart', (evt) => {
                source.clear();
                sketch = evt.feature;
                const tooltip = this.measureTooltipElement;
                const geom = sketch.getGeometry();
                listener = () => {

                    let output;
                    if (type === 'LineString') {
                        const length = geom.getLength();
                        output = length > 1000 ? `距离：${(length / 1000).toFixed(2)} 千米` : `距离：${length.toFixed(2)} 米`;
                    } else if (type === 'Polygon') {
                        const area = geom.getArea();
                        output = area > 10000 ? `面积：${(area / 10000).toFixed(2)} 公顷` : `面积：${area.toFixed(2)} 平方米`;
                    }
                    tooltip.innerHTML = output;
                    tooltipOverlay.setPosition(geom.getLastCoordinate());
                };

                geom.on('change', listener);
            });

            drawInteraction.on('drawend', (evt) => {
                const geom = evt.feature.getGeometry();
                let output;
                if (type === 'LineString') {
                    const length = Math.round(geom.getLength() * 100) / 100;
                    output = `距离：${length} 米`;
                } else if (type === 'Polygon') {
                    const area = Math.round(geom.getArea() * 100) / 100;
                    output = `面积：${area} 平方米`;
                }

                alert(output);

                // 清理绘制内容
                source.clear();
                map.removeInteraction(drawInteraction);
                map.removeOverlay(tooltipOverlay);
                this.measureInteraction = null;
                this.measureTooltipElement = null;
            });

            map.addInteraction(drawInteraction);
        },
        togglePopup() {
            this.showPopup = !this.showPopup;

            // 更新按钮文字中的状态
            const popupButton = this.toolGroups
                .flatMap(group => group.buttons)
                .find(btn => btn.text.includes('弹窗'));

            if (popupButton) {
                popupButton.text = `弹窗 ${this.showPopup ? '(开)' : '(关)'}`;
            }
        },
        initLayerControl() {
            const layers = this.map.getLayers().getArray();

            this.layerGroups = this.layerGroups.map(group => ({
                ...group,
                layers: layers
                    .filter(layer => {
                        const title = layer.get('title') || '';
                        return group.name === 'base' && title.startsWith('base') ||
                            group.name === 'vector' && title.startsWith('vector') ||
                            group.name === 'raster' && title.startsWith('raster') ||
                            group.name === 'overlay';
                    })
                    .map(layer => {
                        const key = layer.get('name');
                        const existing = group.layers.find(l => l.key === key);
                        return {
                            key,
                            name: this.layerLabels[key] || key,
                            visible: existing?.visible ?? layer.getVisible(),
                            opacity: existing?.opacity ?? layer.getOpacity(),
                            zIndex: layer.getZIndex() || 0
                        };
                    })
            }));
        },
        onDragEnd(groupName) {
            const group = this.layerGroups.find(g => g.name === groupName);
            const layerKeys = group.layers.map(l => l.key);

            // 获取当前地图上所有图层
            const mapLayers = this.map.getLayers().getArray();

            // 按照新的顺序重新设置图层层级
            layerKeys.forEach((key, newIndex) => {
                const layer = mapLayers.find(l => l.get('name') === key);
                if (layer) {
                    const oldIndex = mapLayers.indexOf(layer);
                    if (oldIndex !== -1 && oldIndex !== newIndex) {
                        this.map.getLayers().removeAt(oldIndex);
                        this.map.getLayers().insertAt(newIndex, layer);
                    }
                }
            });
        },
        toggleParamsForm() {
            this.showParamsForm = !this.showParamsForm;
            console.log('参数表单状态:', this.showParamsForm);
        },
        handleAcquireVectorTiles(params) {
            const url = '/spatial/acquireVectorTiles';

            this.axios.get(url, { params })
                .then(response => {
                    if (response.data.success) {
                        alert(response.data.message);
                        console.log('切片路径:', response.data.result);
                    } else {
                        alert('获取失败: ' + (response.data.message || '未知错误'));
                    }
                })
                .catch(error => {
                    console.error('请求失败:', error);
                    alert('请求失败，请查看控制台日志');
                });
        },
        handleResetParams(resetParams) {
            this.vectorTileParams = resetParams;
        },
        toggleParamsRasterForm() {
            this.showRasterForm = !this.showRasterForm;
            console.log('参数表单状态:', this.showRasterForm);
        },
        toggleFullScreen() {
            const mapContainer = this.$refs.mapContainer;
            if (!document.fullscreenElement) {
                // 进入全屏
                mapContainer.requestFullscreen().catch(err => {
                    alert("无法进入全屏：" + err.message);
                });
                this.fullScreen = true;
            } else {
                // 退出全屏
                document.exitFullscreen();
                this.fullScreen = false;
            }

            // 无论进入还是退出都要调整地图尺寸
            setTimeout(() => {
                if (this.map) {
                    this.map.updateSize();
                    this.map.getView().fit(this.map.getView().calculateExtent(this.map.getSize()));
                }
            }, 300); // 给 DOM 更新一点时间
        },
        toggleGroup(group) {
            group.expanded = !group.expanded;
        },

    }
}
</script>

<style scoped>
.map {
    width: 100%;
    height: 100vh;
    position: relative;
    position: relative;
    overflow: hidden;
}

.mouse-position {
    position: absolute;
    bottom: 10px;
    left: 10px;
    padding: 6px 12px;
    background: rgba(255, 255, 255, 0.7);
    border-radius: 4px;
    font-size: 14px;
    color: #333;
    pointer-events: none;
    z-index: 999;
}

.ol-popup {
    position: absolute;
    background-color: white;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #cccccc;
    bottom: 12px;
    left: -50px;
    min-width: 280px;
}

.ol-popup:after,
.ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
}

.ol-popup:after {
    border-top-color: white;
    border-width: 10px;
    left: 48px;
    margin-left: -10px;
}

.ol-popup:before {
    border-top-color: #cccccc;
    border-width: 11px;
    left: 48px;
    margin-left: -11px;
}

.ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
}

.ol-popup-closer:after {
    content: "✖";
}

/* 地图工具箱 */
.map-tools-container {
    position: absolute;
    top: 12px;
    left: 10px;
    z-index: 1000;
    width: 260px;
    background-color: #ffffff;
    border-radius: 10px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    overflow: hidden;
    transition: all 0.3s ease;
}

.tool-group {
    border-bottom: 1px solid #e4e4e4;

    &:last-child {
        border-bottom: none;
    }
}

.tool-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background-color: #f7f9fb;
    font-size: 14px;
    font-weight: bold;
    color: #2c3e50;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.2s ease;
}

.tool-group-header:hover {
    background-color: #ecf0f1;
}

.tool-group-header .arrow {
    font-size: 12px;
    transition: transform 0.3s ease;
}

.tool-group-buttons {
    padding: 8px 10px;
    background-color: #fbfbfb;
}

.tool-group-buttons button {
    width: 100%;
    display: block;
    padding: 8px 12px;
    margin-bottom: 6px;
    font-size: 14px;
    font-weight: 500;
    color: #333;
    background-color: #ffffff;
    border: 1px solid #ddd;
    border-radius: 6px;
    text-align: left;
    cursor: pointer;
    transition: all 0.2s ease;
}

.tool-group-buttons button:hover {
    background-color: #f0f0f0;
    transform: translateX(2px);
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
}

.tool-group-buttons button:active {
    background-color: #e0e0e0;
    transform: scale(0.99);
}

/* 折叠动画 */
.slide-enter-active,
.slide-leave-active {
    transition: max-height 0.3s ease-out;
    overflow: hidden;
}

.slide-enter,
.slide-leave-to {
    max-height: 0;
}

.shp-upload-container {
    padding: 8px 10px;
    background-color: #fbfbfb;
}

.shp-upload-label {
    display: block;
    border: 2px dashed #ccc;
    border-radius: 6px;
    padding: 12px;
    text-align: center;
    cursor: pointer;
    transition: border-color 0.3s ease;

    &:hover {
        border-color: #409EFF;
    }
}

.upload-button {
    display: inline-block;
    padding: 6px 12px;
    background-color: #409EFF;
    color: white;
    font-size: 14px;
    border-radius: 4px;
    margin-bottom: 8px;
    cursor: pointer;
}

.file-name {
    display: block;
    margin-top: 8px;
    font-size: 13px;
    color: #555;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;

    &.error {
        color: red;
    }
}

.ol-tooltip {
    position: relative;
    background-color: rgba(0, 0, 0, 0.7);
    border-radius: 4px;
    color: white;
    padding: 4px 8px;
    font-size: 12px;
    white-space: nowrap;
    z-index: 1000;
}

.widget-wrapper {
    position: absolute;
    bottom: 20px;
    /* 距离底部的距离 */
    right: 50px;
    /* 距离右侧的距离 */
    z-index: 1000;
    /* 确保组件显示在地图之上 */
}
</style>